#include "snakewidget.h"
#include "snack_settings.h"
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QColor>
#include <QKeyEvent>
#include <QDebug>
#include <time.h>
#include <QVector>
#include <QRect>
#include <QMessageBox>
#include <QTimer>
#include "globalutils.h"
#include <QCoreApplication>
SnakeWidget::SnakeWidget( QWidget* parent):QWidget (parent)
{
    init();
}
SnakeWidget::~SnakeWidget(){
    delete brush;
    delete pen;
    delete bgColor;
}

/**
 * 初始化
 * @brief SnakeWidget::init
 */
void SnakeWidget::init(){
    //无边框
    this->setWindowFlags(Qt::FramelessWindowHint);
    hide();
    brush =  new QBrush(); //画刷
    pen = new QPen(); //画笔
    bgColor = new QColor(GAME_BG_CLOLR);
    snake = new QVector<SnakeNode*>();
    //初始蛇头的图片
    snakeHead = QPixmap(QCoreApplication::applicationDirPath().append("/resources/snake.png"));
    //缩放
    snakeHead = snakeHead.scaled(GRID_WIDTH , GRID_WIDTH,Qt::KeepAspectRatio);
    timer = new QTimer(this);
    //事件
    connect(timer,SIGNAL(timeout()),this,SLOT(timeMove()));
    show();
   // startGame();
}

/**
 * 清除数据
 * @brief SnakeWidget::clearData
 */
void SnakeWidget::clearData(){

    for(SnakeNode * node : *snake){
        delete node; //回收内存
    }
    //清空集合
    snake->clear();

}
/**
 * 初始化贪吃蛇
 * @brief SnakeWidget::initSnake
 */
void SnakeWidget::startGame(){
    if(gameStatus == 1){ //游戏已经在进行中
        return;
    }
    currrentLevleScore = 0;//当前关卡得分
    passRequiredScore = level * 2 * SCORE_FACTOR; //当前关卡通过需要的分数

//    QString msg = "第";
//    msg.append(QString::number(level,10));
//    msg.append("关,过关需要分数:");
//    msg.append(QString::number(passRequiredScore,10));
//    msg.append(",当前总分:");
//    msg.append(QString::number(totalScore,10));
//    QMessageBox::about(this, "提示",msg);

    //发信号
    emit signalGameStart(level, passRequiredScore);
    emit signalGetScore(totalScore, currrentLevleScore);
    gameStatus = 1;//更新游戏状态
    //添加一个节点作为头部
    SnakeNode * node  = getRandomNode(10);
    if(node->getX() > width() - 100){
        node->setX(width() - 100);//防止太靠边
    }
    snake->push_front(node);
    //随机产生一个食物节点
    foodNode = getRandomNode(11);
    update();
    //自动移动
    autoMove();
}
/**
 * 绘制事件
 * @brief SnakeWidget::paintEvent
 */
void SnakeWidget::paintEvent(QPaintEvent *){
    QPainter painter(this);
    drawBg(painter);
    if(gameStatus == 1){
        drawSnake(painter);
        drawFood(painter);
    }
}

/**
 * 绘制背景
 * @brief SnakeWidget::drawBg
 * @param painter
 */
void SnakeWidget::drawBg(QPainter &painter){
    //1、绘制游戏背景
    brush->setStyle(Qt::BrushStyle::SolidPattern);
    brush->setColor(*bgColor);
    pen->setColor(*bgColor);
    painter.setPen(*pen);
    painter.setBrush(*brush);
    painter.drawRect(0, 0, width(), height()); //绘制矩形

    //2、绘制网格
    brush->setStyle(Qt::BrushStyle::NoBrush);
    pen->setColor(Qt::gray);
    pen->setStyle(Qt::PenStyle::DashLine);
    painter.setPen(*pen);
    painter.setBrush(*brush);
    int winWidth = width();
    int winHeight = height();
    //绘制竖线
    int i;
    for(i = 1; i < winWidth/GRID_WIDTH; i++){
        painter.drawLine(i * GRID_WIDTH, 0, i * GRID_WIDTH, winHeight);
    }
    //绘制横线
    for(i = 1; i < winHeight/GRID_WIDTH; i++){
         painter.drawLine(0,i * GRID_WIDTH, winWidth, i * GRID_WIDTH);
    }
}

/**
 * 绘制snake
 * @brief SnakeWidget::drawSnake
 * @param painter
 */
void SnakeWidget::drawSnake(QPainter &painter){
    //3、绘制snake
    //设置画笔
    brush->setStyle(Qt::BrushStyle::SolidPattern);
    brush->setColor(Qt::green);
    pen->setColor(Qt::red);
    pen->setStyle(Qt::PenStyle::SolidLine);
    painter.setPen(*pen);
    painter.setBrush(*brush);
    QRect rect;//位置
    QVector<SnakeNode *>::iterator iter = snake->begin();

    //3.1绘制蛇头
    //矩阵
    QMatrix matrix;
    //旋转
    matrix = matrix.rotate(getHeadRotateAngle());
    //变换
    snakeHead = snakeHead.transformed(matrix);
    painter.drawPixmap((*iter)->getX(),(*iter)->getY(),snakeHead);//绘制一个图像

    //3.2绘制节点
    for(iter++; iter != snake->end(); iter++){
        rect.setX((*iter)->getX() + GRID_WIDTH/5);
        rect.setY((*iter)->getY() + GRID_WIDTH/5);
        rect.setWidth(GRID_WIDTH - GRID_WIDTH/5*2);
        rect.setHeight(GRID_WIDTH - GRID_WIDTH/5*2);
        //绘制椭圆
        painter.drawEllipse(rect);
    }
}

/**
 * 绘制食物节点
 * @brief SnakeWidget::drawFood
 * @param painter
 */
void SnakeWidget::drawFood(QPainter &painter){
    //设置画笔
    brush->setStyle(Qt::BrushStyle::SolidPattern);
    brush->setColor(Qt::yellow);
    pen->setColor(Qt::green);
    pen->setStyle(Qt::PenStyle::SolidLine);
    painter.setPen(*pen);
    painter.setBrush(*brush);
    QRect rect(foodNode->getX(), foodNode->getY(), GRID_WIDTH, GRID_WIDTH);
    //绘制椭圆
    painter.drawEllipse(rect);
}

/**
 * 随机创建一个节点
 * @brief SnakeWidget::getRandomNode
 * @param dsSeed
 * @return
 */
SnakeNode * SnakeWidget::getRandomNode(int dsSeed){
    uint seed_x = static_cast<uint>(clock());
    //随机获取x,y坐标
    int x = GlobalUtils::getRandomNum(seed_x,width());
    int y = GlobalUtils::getRandomNum(seed_x+static_cast<uint>(abs(dsSeed +23)),width());
    //获取整数倍
    x = x / GRID_WIDTH * GRID_WIDTH;
    y = y / GRID_WIDTH * GRID_WIDTH;
    //添加一个节点作为头部
    SnakeNode * node  = new SnakeNode(x, y, this); //指定this作为parent，让qt管理内存释放
    return node;
}

/**
 * 移动
 * @brief SnakeWidget::snakeMove
 */
void SnakeWidget::snakeMove(){
    if(gameStatus == 0){
        return;
    }
    //头更新头节点的位置
    SnakeNode * head = snake->at(0);
    switch (currentDirection) {
        case Direction::LEFT://左
            if(head->getX() - GRID_WIDTH == foodNode->getX()
                    && head->getY() == foodNode->getY()){ //是否吃到了食物
                eatEvent();
            }else{
                moveNode();
                moveOneNode(head, head->getX() - GRID_WIDTH, head->getY());//左移
               // head->setX(head->getX() - GRID_WIDTH);//左移
            }
        break;
        case Direction::DOWN://下
            if(head->getY() + GRID_WIDTH == foodNode->getY()
                    && head->getX() == foodNode->getX()){ //是否吃到了食物
                eatEvent();
            }else{
                moveNode();
                //head->setY(head->getY() + GRID_WIDTH);//下移
                moveOneNode(head, head->getX(), head->getY() + GRID_WIDTH);
            }
        break;
        case Direction::RIGHT: //右
            if(head->getX() + GRID_WIDTH == foodNode->getX()
                    && head->getY() == foodNode->getY()){ //是否吃到了食物
                eatEvent();
            }else{
                moveNode();
                //head->setX(head->getX() + GRID_WIDTH);//右移
                moveOneNode(head, head->getX() + GRID_WIDTH, head->getY());
            }
        break;
        case Direction::ON: //上
            if(head->getY() - GRID_WIDTH == foodNode->getY()
                    && head->getX() == foodNode->getX()){ //是否吃到了食物
                eatEvent();
            }else{
                moveNode();
                //head->setY(head->getY() - GRID_WIDTH);//上移
                moveOneNode(head, head->getX(), head->getY() - GRID_WIDTH);
            }
        break;
    }
    update(); //重新绘制
    //检查是否死了
    if(checkDie()){
        gameOver();
    }
}

/**
 * 移动节点
 * @brief SnakeWidget::moveNode
 */
void SnakeWidget::moveNode(){
    //更新节点位置(后一个节点的位置设置为前一个节点的位置)
    QVector<SnakeNode*>::iterator it = snake->end();
    for(it--; it != snake->begin(); it--){
        moveOneNode((*it), (*(it-1))->getX(), (*(it-1))->getY());
//        (*it)->setX((*(it-1))->getX());
//        (*it)->setY((*(it-1))->getY());
    }
}

/**
 * 移动单个节点
 * @brief moveOneNode
 * @param node 节点
 * @param nextX 下个位置 x
 * @param nextY 下个位置 y
 */
void SnakeWidget::moveOneNode(SnakeNode *node, int nextX, int nextY){
    node->setX(nextX);
    node->setY(nextY);
}

/**
 * 自动移动
 * @brief SnakeWidget::autoMove
 */
void SnakeWidget::autoMove(){
    //启动 QTimer
    timer->start(500 - level * 10); //关卡越高移动越快
}

/**
 * 停止定时移动
 * @brief SnakeWidget::stopAutoMove
 */
void SnakeWidget::stopAutoMove(){
    timer->stop();//停止定时器
}

/**
 *
 * 吃到食物
 * @brief SnakeWidget::eatEvent
 */
void SnakeWidget::eatEvent(){
    snake->push_front(foodNode); //加入节点集合
    foodNode = getRandomNode(12); //产生新的食物节点
    update();//更新界面
    //更新得分
    totalScore += 10;
    currrentLevleScore +=10;
    //发信号
    emit signalGetScore(totalScore, currrentLevleScore);

    if(currrentLevleScore >= passRequiredScore){
        passLevel();//通关
    }


}
/**
 * 检测是否死了
 * @brief SnakeWidget::checkDie
 * @return
 */
bool SnakeWidget::checkDie(){
    SnakeNode * head = snake->at(0);
    //是否出界
    if(head->getX() >= width() || head->getX() < 0
            || head->getY() >= height() || head->getY() < 0){
        return true;
    }
    //是否碰到了自己
    for(QVector<SnakeNode *>::iterator it = snake->begin()+1; it != snake->end(); it++){
        if(head->getX() == (*it)->getX() && head->getY() == (*it)->getY()){
            return true;
        }
    }
    return false;
}
/**
  游戏结束
 * @brief SnakeWidget::gameOver
 */
void SnakeWidget::gameOver(){
    gameStatus = 0;//游戏结束
    stopAutoMove();
    QMessageBox::about(this, "失败", "GameOver");
    totalScore = 0;
    level = 1;
    clearData();
}

/**
  游戏过关
 * @brief SnakeWidget::gameOver
 */
void SnakeWidget::passLevel(){
    gameStatus = 0;//游戏结束
    stopAutoMove();
    clearData();
    int r = QMessageBox::information(this, tr("提示"),
                                         tr("恭喜通关,进入下一关?"),
                                         QObject::tr(("确认")) , QObject::tr(("取消")));
            if (r == QObject::tr(("确认")).toInt()) {
               level +=1;
               startGame();
            }

   // DialogResult dr=MessageBox.Show("确认删除吗？", "提示", MessageBoxButtons.OKCancel); if (dr == DialogResult.OK) { //用户选择确认的操作 MessageBox.Show("您选择的是【确认】"); } else if (dr == DialogResult.Cancel) { //用户选择取消的操作 MessageBox.Show("您选择的是【取消】"); }
}



/**
 * 键盘事件
 * @brief SnakeWidget::keyPressEvent
 * @param event
 */
void SnakeWidget::keyPressEventFromWindow(QKeyEvent *event){
    if(gameStatus == 0){ //游戏已结束
        return;
    }
    switch (event->key()) {
        case Qt::Key::Key_A:
        {
            if(currentDirection != Direction::RIGHT){
                    currentDirection = Direction::LEFT; //更新方向
                    snakeMove();
            }
         break;
        }
        case Qt::Key::Key_S:
        {
            if(currentDirection != Direction::ON){
                    currentDirection = Direction::DOWN; //更新方向
                    snakeMove();
            }
            break;
        }
        case Qt::Key::Key_D:
        {
            if(currentDirection != Direction::LEFT){
                    currentDirection = Direction::RIGHT; //更新方向
                    snakeMove();
            }
            break;
        }
        case Qt::Key::Key_W:
        {
            if(currentDirection != Direction::DOWN){
                    currentDirection = Direction::ON; //更新方向
                    snakeMove();
            }
            break;
        }
        default:
            break;
    }
}

/**
 * 获取蛇头旋转的角度
 * @brief SnakeWidget::getHeadRotateAngle
 * @return
 */
int SnakeWidget::getHeadRotateAngle(){
     int angle = (currentDirection - oldDirection) * 90;
     oldDirection = currentDirection;
     return angle;
}

void SnakeWidget::timeMove(){
    snakeMove();
}
